package org.dizena.gateway.filter;

import lombok.extern.slf4j.Slf4j;
import org.dizena.common.base.enums.EnumHeaderKey;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import java.util.function.Consumer;

@Slf4j
@Component
public class GatewayTraceFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        // .....
        ServerHttpRequest serverHttpRequest = exchange.getRequest();
        HttpHeaders headers = serverHttpRequest.getHeaders();

        // 封装需要向后续封装的header对象
        LinkedHashMap<String, String> headerMap = new LinkedHashMap<>();

        String reqId = headers.getFirst(EnumHeaderKey.TRACE_ID.getKey());
        if (reqId == null) {
            reqId = UUID.randomUUID().toString().toLowerCase().replaceAll("-", "");
            headerMap.put(EnumHeaderKey.TRACE_ID.getKey(), reqId);
        }

        String reqIp = headers.getFirst(EnumHeaderKey.REQUEST_IP.getKey());
        if (reqIp == null) {
            reqIp = serverHttpRequest.getRemoteAddress().getAddress().getHostAddress();
            headerMap.put(EnumHeaderKey.REQUEST_IP.getKey(), reqIp);
        }

        log.info("1001 gateway traceId {},reqIp {}", reqId, reqIp);

        chainFilterAndSetHeaders(chain, exchange, headerMap);

        // .....

        //调用chain.filter继续向下游执行
        return chain.filter(exchange);

    }

    /**
     * 顺序,数值越小,优先级越高
     *
     * @return
     */
    @Override
    public int getOrder() {
        return 1;
    }

    /**
     * 设置向后传递的header
     *
     * @param chain
     * @param exchange
     * @param headerMap
     */
    private Mono<Void> chainFilterAndSetHeaders(GatewayFilterChain chain, ServerWebExchange exchange, LinkedHashMap<String, String> headerMap) {
        // 添加header
        Consumer<HttpHeaders> httpHeaders = httpHeader -> {
            for (Map.Entry<String, String> entry : headerMap.entrySet()) {
                // 遍历Map设置header，向后传递
                httpHeader.set(entry.getKey(), entry.getValue());
            }
        };

        ServerHttpRequest newRequest = exchange.getRequest().mutate().headers(httpHeaders).build();
        ServerWebExchange build = exchange.mutate().request(newRequest).build();
        //将现在的request 变成 exchange对象
        return chain.filter(build);
    }
}
